#include <iostream>
#include <zlib/eventsystem/I_EventProcessor.h>
#include <zlib/net/I_UnixNetProcessor.h>
#include <zlib/lib/Ink_sock.h>

using namespace std;

class TestServer : public Continuation
{
public:
	TestServer()
	{
		buff = new MIOBuffer;
		reader = buff->alloc_reader();
		SET_HANDLER(&TestServer::ioEvent);
	}

	void init(UnixNetVConnect *avc)
	{
		vc = avc;
		read_vio = vc->do_io_read(this, buff);
		write_vio = vc->do_io_write(this, reader);
	}

	int ioEvent(int event, void *data)
	{
		//do not use vio
		VIO *vio = (VIO *)data;
		if(event == VC_EVENT_READ_READY)
		{
			cout << "READ_READY.................." << endl;
			IOBufferReader *reader_tmp = reader->clone();
			int64_t len = reader_tmp->read_alive();
			ink_write(2, reader_tmp->start(), len);
			reader_tmp->consum(len);
			reader_tmp->dealloc();
			//echo client
			write_vio->reenable();
			return EVENT_CONT;
		}else if(event == VC_EVENT_READ_COMPLATE)
		{
			cout << "READ_COMPLATE.............." << endl;
			vc->do_io_close(0);
			delete this;
			return EVENT_DONE;
		}else if(event == VC_EVENT_WRITE_READY)
		{
			cout << "WRITE_READY................" << endl;
			//notify read
			read_vio->reenable();
			return EVENT_CONT;
		}else if(event == VC_EVENT_WRITE_COMPLATE)
		{
			cout << "WRITE_COMPLATE........" << endl;
			vc->do_io_close(0);
			delete this;
			return EVENT_DONE;
		}else if(event == VC_EVENT_EOS)
		{
			cout << "EOS EVENT.............." << endl;
			vc->do_io_close(0);
			delete this;
			return EVENT_DONE;
		}else if(event == VC_EVENT_ERROR)
		{
			cout << "ERROR...." << endl;
			vc->do_io_close(0);
			delete this;
			return EVENT_DONE;
		}
	}

private:
	MIOBuffer *buff;
	IOBufferReader *reader;

	VIO *read_vio;
	VIO *write_vio;

	UnixNetVConnect *vc;
};


class TestAccept : public Continuation
{
public:
	TestAccept()
	{
		cout << "init test accept success" << endl;
		SET_HANDLER(&TestAccept::acceptEvent);
	}

	int acceptEvent(int event, void *data)
	{
		UnixNetVConnect *vc = (UnixNetVConnect *)data;
		if(event == NET_EVENT_ACCEPT)
		{
			cout << "accept success:" << vc->fd << endl;
			TestServer *server = new TestServer;
			server->mutex = new_ProxyMutex();
			server->init(vc);
		}else{
			cout << "accept faild" << endl;
			vc->do_io_close(0);
		}
	}
};

int main()
{
	eventProcessor.start(1);
	netProcessor.start(0);//reuse ET_CALL Thread group
	IpEntry bind_entry;
	bind_entry.init(AF_INET, "127.0.0.1", 8888);
	AcceptOptions opt;

	TestAccept accepter;
	accepter.mutex = new_ProxyMutex();
	netProcessor.accept(&accepter, 1, bind_entry, opt);

	while(1)
	{
		sleep(10);
	}

	return 0;
}
